#include "cpu/exec/template-start.h"

#define instr mov

static void do_execute() {
	OPERAND_W(op_dest, op_src->val);
	print_asm_template2();
}

make_instr_helper(i2r)
make_instr_helper(i2rm)
make_instr_helper(r2rm)
make_instr_helper(rm2r)

make_helper(concat(mov_a2moffs_, SUFFIX)) {
	swaddr_t addr = instr_fetch(eip + 1, 4);
	MEM_W(addr, REG(R_EAX), R_DS);

	print_asm("mov" str(SUFFIX) " %%%s,0x%x", REG_NAME(R_EAX), addr);
	return 5;
}

make_helper(concat(mov_moffs2a_, SUFFIX)) {
	swaddr_t addr = instr_fetch(eip + 1, 4);
	REG(R_EAX) = MEM_R(addr, R_DS);

	print_asm("mov" str(SUFFIX) " 0x%x,%%%s", addr, REG_NAME(R_EAX));
	return 5;
}

#if DATA_BYTE == 2

make_helper(mov_rm2sreg_w) {
	uint8_t modrm, reg, sreg;
	modrm = instr_fetch(cpu.eip + 1, 1);
	reg = modrm & 7;
	sreg = (modrm >> 3) & 7;

	cpu.sreg[sreg].selector = reg_w(reg);

	sreg_load(sreg);

	print_asm("mov %s, sreg%d", REG_NAME(reg), sreg);
	return 2;
}

#endif

#if DATA_BYTE == 4

make_helper(concat(mov_r2cr_, SUFFIX)) {
	uint8_t modrm = instr_fetch(eip + 1, 1);
	uint8_t crnum = (modrm >> 3) & 0x7;
	uint8_t regnum = modrm & 7;

	if (crnum == 0) {
		cpu.cr0.val = reg_l(regnum); 
	} else if (crnum == 3) {
		cpu.cr3.val = reg_l(regnum);
	} else {
		Assert(0, "Don't support mov instr of cr %d\n", crnum);
	}
	print_asm("mov" str(SUFFIX) " %%%s, cr%d", REG_NAME(R_EAX), crnum);

	return 2;
}

make_helper(concat(mov_cr2r_, SUFFIX)) {
	uint8_t modrm = instr_fetch(eip + 1, 1);
	uint8_t crnum = (modrm >> 3) & 0x7;
	uint8_t regnum = modrm & 7;

	if (crnum == 0) {
		reg_l(regnum) = cpu.cr0.val; 
	} else if (crnum == 3) {
		reg_l(regnum) = cpu.cr3.val; 
	} else {
		Assert(0, "Don't support mov instr of cr %d\n", crnum);
	}

	print_asm("mov" str(SUFFIX) " cr%d, %%%s", crnum, REG_NAME(R_EAX));

	return 2;
}

#endif

#include "cpu/exec/template-end.h"
